package org.example.java.ref;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.WeakHashMap;
import org.example.java.ref.WeakHashMapTest.Key;

/**
 * -Xmx20M -XX:+PrintGCDetails WeakHashMap OutOfMemory 一般不会出现问题是因为不会map list Created by juntaozhang
 * on 3/19/15.
 */
public class WeakHashMapOOM {
  static class Key {
    String id;

    public Key(String id) {
      this.id = id;
    }

    public String toString() {
      return id;
    }

    public int hashCode() {
      return id.hashCode();
    }

    public boolean equals(Object r) {
      return (r instanceof WeakHashMapTest.Key)
          && id.equals(((WeakHashMapTest.Key) r).id);
    }

    public void finalize() {
      System.out.println("Finalizing Key " + id);
    }
  }

  public static void main(String[] args) {
    test0();
//    test();
//    test1();
//    test2();
//    test3();
//    test4();
  }

  private static void test0() {
    WeakHashMap<Integer, byte[]> d = new WeakHashMap<>();
    for (int i = 0; i < 100; i++) {
      System.out.println(i);
      //下面两行区别?
      //int i存在栈中不会被gc,new Integer(i)存放在堆中
//      d.put(i, new byte[1024 * 1024]);//value 导致的OOM
      d.put(new Integer(i), new byte[1024 * 1024]);//正常进行
    }
    System.out.println("size=>"+d.size());
  }

  private static void test() {
    WeakHashMap<Key, byte[]> d = new WeakHashMap<>();
    for (int i = 0; i < 100; i++) {
      System.out.println(i);
      d.put(new Key(String.valueOf(i)), new byte[1024 * 1024]);//正常进行
    }
    System.out.println(d.size());
  }

  private static void test1() {
    List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<>();
      d.put(new byte[1024][4000], new byte[1024][4000]);//value 导致的OOM
      d.put(new byte[1024][4001], new byte[1024][4000]);
      maps.add(d);
      System.gc();
      System.out.println(i);
    }
  }

  private static void test2() {
    List<WeakHashMap<byte[][], byte[][]>> maps = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      WeakHashMap<byte[][], byte[][]> d = new WeakHashMap<>();
      d.put(new byte[1024][4000], new byte[1024][4000]);
      d.put(new byte[1024][4001], new byte[1024][4000]);
      maps.add(d);
      System.gc();
      System.out.println(i);
      for (int j = 0; j <= i; j++) {
        System.out.println(j + " size = " + maps.get(j).size());// size 触发 expungeStaleEntries
      }
    }
  }

  private static void test3() {
    List<WeakHashMap<byte[][], Object>> maps = new ArrayList<>();
    for (int i = 0; i < 2000; i++) {
      WeakHashMap<byte[][], Object> d = new WeakHashMap<>();
      d.put(new byte[1000][1000], new Object());//Object 过多也会导致OOM 只是目前没有表现出来 不安全
      maps.add(d);
      System.gc();
      System.out.println(i);
    }
  }

  private static void test4() {
    List<WeakHashMap<byte[][], WeakReference<byte[][]>>> maps = new ArrayList<>();//解决value 导致的OOM，但是WeakReference本身地址空间没有释放
    for (int i = 0; i < 100; i++) {
      WeakHashMap<byte[][], WeakReference<byte[][]>> d = new WeakHashMap<>();
      d.put(new byte[1000][1000], new WeakReference<>(new byte[1000][1000]));
      maps.add(d);
      System.gc();
      System.out.println(i);
    }
  }
}
